#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>

#include <xtensa/xtruntime.h>

#include "tasks.h"
#include "co_mem.h"

#include "audio_algorithm.h"

#include "cvsd_plc.h"
#include "aec_core.h"
#include "noise_suppression.h"
#include "gain_control.h"
#include "echo_cancellation.h"

#include "plf.h"
#include "ipc.h"
#include "uart.h"
#include "user_def.h"
#include "hal_gpio.h"
#include "y_ringbuf.h"
#include "adpcm-pcm.h"

#define AUDIO_ALGO_LOG				//printf
#define AUDIO_ALGO_SPK_LOG          0
#define AUDIO_ALGO_ESCO_OUT_LOG     0
#define AUDIO_ALGO_MIC_LOG          0
#define AUDIO_ALGO_ESCO_IN_LOG      0
#define AUDIO_ALGO_PTR_LOG          0

#define AUDIO_ALGO_DBG_WITH_IO      0

#define REG_PL_WR(addr, data)       *(volatile uint32_t *)(addr) = (data)
#define REG_PL_RD(addr)             *(volatile uint32_t *)(addr)

#define ENABLE_PLC          0//1
#define ENABLE_AEC          0//1
#define ENABLE_NS           0//1
#define ENABLE_AGC          0//1

char char2ascii[] = "0123456789abcdef";

struct audio_algorithm_t *audio_algorithm_env = NULL;

#define AEC_OUT_BUFFER_FRAME_COUNT  6
#define AUDIO_ALG_FRAME_SIZE        30
#define AUDIO_ALG_AEC_SIZE          160
#define AUDIO_ALG_AEC_OFFSET        (AUDIO_ALG_AEC_SIZE + 30)   //1A 1B ֮ľ
#define PLC_BUFFER_MAX              900     //30X
#define LOCAL_IN_BUFFER_MAX         900     //30X
#define AEC_OUT_BUFFER_MAX          (AUDIO_ALG_AEC_SIZE*AEC_OUT_BUFFER_FRAME_COUNT)

#define IPC_DMA_RX_INT_OCCURED      0x01
#define IPC_DMA_TX_INT_OCCURED      0x02

// 1. 文件顶部增加全局变量
static volatile bool g_cur_frame_from_mcu = false;

struct audio_algorithm_t {
    int16_t plc_buffer[PLC_BUFFER_MAX];
    uint32_t plc_in_data_state;         //ÿһشһ֡ݵ״̬,PLC_BUFFER_MAXҪ960
    int16_t plc_buffer_insert_offset;  //Զݶָ1D
    int16_t plc_buffer_write_offset;   //PLC ݵָ1C
    int16_t plc_buffer_read_offset;    //д뵽codecָ1B
    int16_t plc_buffer_aec_offset;     //AEC㷨ָ1A
    int16_t plc_buffer_max;

    int16_t local_in_buffer[LOCAL_IN_BUFFER_MAX];
    int16_t local_in_buffer_write_offset;  //2B
    int16_t local_in_buffer_read_offset;   //2A
    int16_t local_in_buffer_max;

    int16_t aec_out_buffer[AEC_OUT_BUFFER_MAX];
    int16_t aec_out_buffer_write_offset;   //3B
    int16_t aec_out_buffer_read_offset;    //3A
    int16_t aec_out_buffer_max;

    // 新增：使用ringbuf管理扬声器数据
    RINGBUF_st *speaker_ringbuf;           // 扬声器数据环形缓冲区

    RINGBUF_st *speaker_to_mcu_ringbuf;           // 扬声器数据环形缓冲区

    uint8_t speaker_data_enable;           // 是否启用扬声器数据发送
    
    // 新增：ADPCM编码器状态
    ima_adpcm_state_t *adpcm_encoder;      // ADPCM编码器状态

    // 新增：MCU ADPCM数据解码相关
    RINGBUF_st *mcu_adpcm_ringbuf;         // MCU ADPCM数据环形缓冲区
    ima_adpcm_state_t *adpcm_decoder;      // ADPCM解码器状态
    int16_t mcu_pcm_buffer[240];  // 临时PCM缓冲区：120字节ADPCM解码后为240个PCM样本

    cvsd_plc_state_t plc_state;
#if ENABLE_AEC
    aec_t *aec_core;
#endif
#if ENABLE_AGC
    void *agc_handle;
#endif
#if ENABLE_NS
    NsHandle *ns_handle;
#endif

    int16_t aec_remote_data[AUDIO_ALG_AEC_SIZE];
    int16_t aec_local_data[AUDIO_ALG_AEC_SIZE];
    uint8_t enable;
    uint8_t ipc_dma_int_occur_status;
    uint8_t launch_algo_msg_count;

    uint8_t rx_toggle;
    uint8_t tx_toggle;

    int16_t *pending_esco_data;
    uint8_t pending_data_ready;
};

#define CO_BIT(x)               (1<<x)
#define AUDIO_ALG_PLC_ENABLE    CO_BIT(3)
#define AUDIO_ALG_AEC_ENABLE    CO_BIT(0)
#define AUDIO_ALG_NR_ENABLE     CO_BIT(1)
#define AUDIO_ALG_AGC_ENABLE    CO_BIT(2)
uint8_t audio_alg_sel = 0/*(AUDIO_ALG_PLC_ENABLE|AUDIO_ALG_AEC_ENABLE|AUDIO_ALG_NR_ENABLE|AUDIO_ALG_AGC_ENABLE)*/;

#define AUDIO_ALGO_PRINT_SEL_ESCO_OUT   CO_BIT(0)
#define AUDIO_ALGO_PRINT_SEL_ESCO_IN    CO_BIT(1)
#define AUDIO_ALGO_PRINT_SEL_MIC        CO_BIT(2)
#define AUDIO_ALGO_PRINT_SEL_SPK        CO_BIT(3)
#define AUDIO_ALGO_PRINT_SEL_PTR        CO_BIT(4)
uint8_t audio_alg_print_sel = 0;

/*�������0,��ʾ����ͨ·��,��Ҫ�þһЩlocal_voice;
    С0,ʾ����ͨ·��,��Ҫ�þһЩremote_voice; */
int16_t aec_shift = -240;

int16_t mic_data[60];
int16_t esco_in_data[60];


  
static bool is_start = false;   

// 新增：声明外部接口
extern uint8_t audio_algorithm_get_mcu_audio_timeout_flag(void);

void audio_algorithm_init(void)
{
    //uint32_t total_buffer_len;
    struct audio_algorithm_t *audio_algorithm_env_tmp;
#if ENABLE_AGC
    WebRtcAgc_config_t agcConfig;
#endif

    audio_algorithm_env_tmp = (struct audio_algorithm_t *)pvPortMalloc(sizeof(struct audio_algorithm_t));
    memset((void *)audio_algorithm_env_tmp, 0, sizeof(struct audio_algorithm_t));

#if ENABLE_AEC
    WebRtcAec_CreateAec(&audio_algorithm_env_tmp->aec_core);
    WebRtcAec_InitAec(audio_algorithm_env_tmp->aec_core, 8000);
#endif
#if ENABLE_AGC
    WebRtcAgc_Create(&audio_algorithm_env_tmp->agc_handle);
#endif
#if ENABLE_NS
    WebRtcNs_Create(&audio_algorithm_env_tmp->ns_handle);
#endif

#if ENABLE_AEC
    //-----------AEC-----------------------
    audio_algorithm_env_tmp->aec_core->targetSupp = -18.4f;
    audio_algorithm_env_tmp->aec_core->minOverDrive = 5.0f;
#endif

#if ENABLE_AGC
    //-----------AGC-----------------------
    WebRtcAgc_Init(audio_algorithm_env_tmp->agc_handle, 0, 255, kAgcModeFixedDigital, 8000);
    agcConfig.compressionGaindB = 20;
    agcConfig.limiterEnable     = 1;
    agcConfig.targetLevelDbfs   = 3;
    WebRtcAgc_set_config(audio_algorithm_env_tmp->agc_handle, agcConfig);
#endif

#if ENABLE_NS
    //-----------NS--------------------
    WebRtcNs_Init(audio_algorithm_env_tmp->ns_handle, 8000);
    WebRtcNs_set_policy(audio_algorithm_env_tmp->ns_handle, 2);
#endif

    //-----------PLC--------------------
    cvsd_plc_init(&audio_algorithm_env_tmp->plc_state);
    
    audio_algorithm_env_tmp->plc_buffer_max = PLC_BUFFER_MAX;
    audio_algorithm_env_tmp->local_in_buffer_max = LOCAL_IN_BUFFER_MAX;
    audio_algorithm_env_tmp->aec_out_buffer_max = AEC_OUT_BUFFER_MAX;
    if(aec_shift > 0) {
        audio_algorithm_env_tmp->local_in_buffer_read_offset = LOCAL_IN_BUFFER_MAX - aec_shift;
    }
    else {
        audio_algorithm_env_tmp->local_in_buffer_read_offset = 0;
    }

    audio_algorithm_env_tmp->plc_buffer_read_offset = PLC_BUFFER_MAX - 8*AUDIO_ALG_FRAME_SIZE;
    if(aec_shift > 0) {
        audio_algorithm_env_tmp->plc_buffer_aec_offset = audio_algorithm_env_tmp->plc_buffer_read_offset;
    }
    else {
        audio_algorithm_env_tmp->plc_buffer_aec_offset = audio_algorithm_env_tmp->plc_buffer_read_offset + aec_shift;
    }

    audio_algorithm_env_tmp->aec_out_buffer_read_offset = (AEC_OUT_BUFFER_FRAME_COUNT - 3) * AUDIO_ALG_AEC_SIZE;

    // 初始化扬声器数据ringbuf
    audio_algorithm_env_tmp->speaker_ringbuf = y_ringbuf_create(AUDIO_ALG_FRAME_SIZE * 50 * sizeof(int16_t));  // 创建8帧大小的ringbuf

    
    audio_algorithm_env_tmp->speaker_to_mcu_ringbuf = y_ringbuf_create(AUDIO_ALG_FRAME_SIZE * 400 * sizeof(int16_t));  // 创建8帧大小的ringbuf


    audio_algorithm_env_tmp->speaker_data_enable = 1;  // 默认启用扬声器数据发送
    
    // 初始化待处理数据变量
    audio_algorithm_env_tmp->pending_esco_data = NULL;
    audio_algorithm_env_tmp->pending_data_ready = 0;

    // 初始化ADPCM编码器
    audio_algorithm_env_tmp->adpcm_encoder = pvPortMalloc(sizeof(ima_adpcm_state_t));
    if(audio_algorithm_env_tmp->adpcm_encoder != NULL) {
        ima_adpcm_init(audio_algorithm_env_tmp->adpcm_encoder, IMA_ADPCM_DVI4);
        printf("ADPCM encoder initialized\r\n");
    } else {
        printf("Failed to allocate ADPCM encoder\r\n");
    }

    // 新增：初始化MCU ADPCM相关组件
    audio_algorithm_env_tmp->mcu_adpcm_ringbuf = y_ringbuf_create(AUDIO_ALG_FRAME_SIZE * 400 * sizeof(int16_t));  // 创建足够大的ringbuf
    audio_algorithm_env_tmp->adpcm_decoder = pvPortMalloc(sizeof(ima_adpcm_state_t));
    if(audio_algorithm_env_tmp->adpcm_decoder != NULL) {
        ima_adpcm_init(audio_algorithm_env_tmp->adpcm_decoder, IMA_ADPCM_DVI4);
        printf("ADPCM decoder initialized\r\n");
    } else {
        printf("Failed to allocate ADPCM decoder\r\n");
    }

    audio_algorithm_env_tmp->enable = true;

    audio_algorithm_env = audio_algorithm_env_tmp;

    AUDIO_ALGO_LOG("audio_algorithm_init: %08x, %d\r\n", audio_algorithm_env, sizeof(struct audio_algorithm_t));
    
    // 添加调试：打印ringbuf创建成功信息
    printf("ringbuf create succeed\r\n");
}

void audio_algorithm_release(void *msg)
{
    struct audio_algorithm_t *audio_algorithm_env_tmp = audio_algorithm_env;

    AUDIO_ALGO_LOG("audio_algorithm_release\r\n");

    _xtos_interrupt_disable(XCHAL_IPC_DMA_RX_INTERRUPT);
    _xtos_interrupt_disable(XCHAL_IPC_DMA_TX_INTERRUPT);

    ipc_dma_rx_int_clear();
    ipc_dma_tx_int_clear();

    if(audio_algorithm_env == NULL) {
        return;
    }

    audio_algorithm_env = NULL;
#if ENABLE_AEC
    WebRtcAec_FreeAec(audio_algorithm_env_tmp->aec_core);
#endif
#if ENABLE_AGC
    WebRtcAgc_Free(audio_algorithm_env_tmp->agc_handle);
#endif
#if ENABLE_NS
    WebRtcNs_Free(audio_algorithm_env_tmp->ns_handle);
#endif

    // 销毁ringbuf
    if(audio_algorithm_env_tmp->speaker_ringbuf != NULL) {
        y_ringbuf_destroy(audio_algorithm_env_tmp->speaker_ringbuf);
    }

    if(audio_algorithm_env_tmp->speaker_to_mcu_ringbuf != NULL) {
        y_ringbuf_destroy(audio_algorithm_env_tmp->speaker_to_mcu_ringbuf);
    }

    

    // 释放ADPCM编码器
    if(audio_algorithm_env_tmp->adpcm_encoder != NULL) {
        ima_adpcm_release(audio_algorithm_env_tmp->adpcm_encoder);
        vPortFree(audio_algorithm_env_tmp->adpcm_encoder);
    }

    // 新增：释放MCU ADPCM相关组件
    if(audio_algorithm_env_tmp->mcu_adpcm_ringbuf != NULL) {
        y_ringbuf_destroy(audio_algorithm_env_tmp->mcu_adpcm_ringbuf);
    }
    if(audio_algorithm_env_tmp->adpcm_decoder != NULL) {
        ima_adpcm_release(audio_algorithm_env_tmp->adpcm_decoder);
        vPortFree(audio_algorithm_env_tmp->adpcm_decoder);
    }

    vPortFree((void *)audio_algorithm_env_tmp);
}

__attribute__((section("iram_section"))) int16_t *audio_algorithm_get_plc_insert_buffer(uint8_t esco_data_mute)
{
    int16_t *buffer;
    uint8_t offset;

    AUDIO_ALGO_LOG("audio_algorithm_get_plc_insert_buffer: %d %d.\r\n", audio_algorithm_env->plc_buffer_insert_offset, esco_data_mute);

    buffer = &audio_algorithm_env->plc_buffer[audio_algorithm_env->plc_buffer_insert_offset];
    offset = audio_algorithm_env->plc_buffer_insert_offset / AUDIO_ALG_FRAME_SIZE;
    if(esco_data_mute) {
        audio_algorithm_env->plc_in_data_state |= (1<<offset);
    }
    else {
        audio_algorithm_env->plc_in_data_state &= (~(1<<offset));
    }
    audio_algorithm_env->plc_buffer_insert_offset += AUDIO_ALG_FRAME_SIZE;
    if(audio_algorithm_env->plc_buffer_insert_offset >= audio_algorithm_env->plc_buffer_max) {
        audio_algorithm_env->plc_buffer_insert_offset = 0;
    }

    return buffer;
}

int16_t *audio_algorithm_get_plc_out_buffer(void)
{
    int16_t *buffer;

    AUDIO_ALGO_LOG("audio_algorithm_get_plc_out_buffer: %d\r\n", audio_algorithm_env->plc_buffer_read_offset);

    buffer = &audio_algorithm_env->plc_buffer[audio_algorithm_env->plc_buffer_read_offset];
    audio_algorithm_env->plc_buffer_read_offset += AUDIO_ALG_FRAME_SIZE;
    if(audio_algorithm_env->plc_buffer_read_offset >= audio_algorithm_env->plc_buffer_max) {
        audio_algorithm_env->plc_buffer_read_offset = 0;
    }

    return buffer;
}

__attribute__((section("iram_section"))) int16_t *audio_algorithm_get_local_in_write_buffer(void)
{
    int16_t *buffer;

    AUDIO_ALGO_LOG("audio_algorithm_get_local_in_write_buffer: %d %d\r\n", audio_algorithm_env->local_in_buffer_write_offset, audio_algorithm_env->local_in_buffer_max);

    buffer = &audio_algorithm_env->local_in_buffer[audio_algorithm_env->local_in_buffer_write_offset];
    audio_algorithm_env->local_in_buffer_write_offset += AUDIO_ALG_FRAME_SIZE;
    if(audio_algorithm_env->local_in_buffer_write_offset >= audio_algorithm_env->local_in_buffer_max) {
        audio_algorithm_env->local_in_buffer_write_offset = 0;
    }

    return buffer;
}

void audio_alg_launch(bool execute)
{
    int16_t *out;
    int16_t store_size, head_len, tail_len, begin;
    uint8_t offset;
    uint32_t out_mic_level;
    uint8_t saturationWarning;
    int16_t out_frame[AUDIO_ALG_AEC_SIZE], out_frame_middle[AUDIO_ALG_AEC_SIZE];

    if(audio_algorithm_env == NULL) {
        return;
    }

    cvsd_plc_state_t *plc_state = &audio_algorithm_env->plc_state;

    GLOBAL_INT_DISABLE();
    //uart_putc_noint('<');

#if AUDIO_ALGO_DBG_WITH_IO
    gpio_set(0);
    //*(volatile uint32_t *)GPIO_DIR = (AUDIO_ALG_AEC_ENABLE|AUDIO_ALG_NR_ENABLE|AUDIO_ALG_AGC_ENABLE);
    //audio_alg_sel = *(volatile uint32_t *)GPIO_DATA;
    //audio_alg_sel = AUDIO_ALG_AEC_ENABLE|AUDIO_ALG_NR_ENABLE;
    //audio_alg_sel = AUDIO_ALG_AEC_ENABLE;
    //audio_alg_sel = 0;
#endif

    out = &audio_algorithm_env->plc_buffer[audio_algorithm_env->plc_buffer_write_offset];
    offset = audio_algorithm_env->plc_buffer_write_offset / AUDIO_ALG_FRAME_SIZE;
    if(audio_algorithm_env->plc_buffer_write_offset >= audio_algorithm_env->plc_buffer_read_offset) {
        store_size = audio_algorithm_env->plc_buffer_write_offset - audio_algorithm_env->plc_buffer_read_offset;
    }
    else {
        store_size = audio_algorithm_env->plc_buffer_write_offset + audio_algorithm_env->plc_buffer_max - audio_algorithm_env->plc_buffer_read_offset;
    }
    audio_algorithm_env->plc_buffer_write_offset += AUDIO_ALG_FRAME_SIZE;
    if(audio_algorithm_env->plc_buffer_write_offset >= audio_algorithm_env->plc_buffer_max) {
        audio_algorithm_env->plc_buffer_write_offset = 0;
    }

#if ENABLE_PLC
    {
        if ((store_size >= 2*AUDIO_ALG_FRAME_SIZE)  //֤readwrite, Ҳ˵ʣЧݲ䲻ӦСһPLCʱ
            &&(audio_algorithm_env->plc_in_data_state & (1<<offset))){
        	AUDIO_ALGO_LOG("audio_alg_launch: plc bad.\r\n");
            if (plc_state->good_frames_nr > CVSD_LHIST/CVSD_FS){
                cvsd_plc_bad_frame(plc_state, out);

                plc_state->bad_frames_nr++;
            }
            else {
                memset(out, 0, CVSD_FS);
            }
        }
        else {
        	AUDIO_ALGO_LOG("audio_alg_launch: plc good.\r\n");

            cvsd_plc_good_frame(plc_state, out);
            plc_state->good_frames_nr++;   
        }
    }
#endif

    if(aec_shift < 0) {
        store_size = (audio_algorithm_env->local_in_buffer_write_offset + audio_algorithm_env->local_in_buffer_max - audio_algorithm_env->local_in_buffer_read_offset) % audio_algorithm_env->local_in_buffer_max;
    }
    else {
        store_size = (audio_algorithm_env->plc_buffer_read_offset + audio_algorithm_env->plc_buffer_max - audio_algorithm_env->plc_buffer_aec_offset) % audio_algorithm_env->plc_buffer_max;
    }
    if(store_size >= AUDIO_ALG_AEC_OFFSET) {
        begin = audio_algorithm_env->plc_buffer_aec_offset;
        tail_len = audio_algorithm_env->plc_buffer_max - begin;
        if(tail_len >= AUDIO_ALG_AEC_SIZE) {
            memcpy(&audio_algorithm_env->aec_remote_data[0], &audio_algorithm_env->plc_buffer[begin], AUDIO_ALG_AEC_SIZE*sizeof(int16_t));

            audio_algorithm_env->plc_buffer_aec_offset += AUDIO_ALG_AEC_SIZE;
            if(audio_algorithm_env->plc_buffer_aec_offset >= audio_algorithm_env->plc_buffer_max) {
                audio_algorithm_env->plc_buffer_aec_offset = 0;
            }
        }
        else {
            memcpy(&audio_algorithm_env->aec_remote_data[0], &audio_algorithm_env->plc_buffer[begin], tail_len*sizeof(int16_t));
            head_len = AUDIO_ALG_AEC_SIZE - tail_len;
            memcpy(&audio_algorithm_env->aec_remote_data[tail_len], &audio_algorithm_env->plc_buffer[0], head_len*sizeof(int16_t));
            audio_algorithm_env->plc_buffer_aec_offset = head_len;
        }

        begin = audio_algorithm_env->local_in_buffer_read_offset;
        tail_len = audio_algorithm_env->local_in_buffer_max - begin;
        if(tail_len >= AUDIO_ALG_AEC_SIZE) {
            memcpy(&audio_algorithm_env->aec_local_data[0], &audio_algorithm_env->local_in_buffer[begin], AUDIO_ALG_AEC_SIZE*sizeof(int16_t));

            audio_algorithm_env->local_in_buffer_read_offset += AUDIO_ALG_AEC_SIZE;
            if(audio_algorithm_env->local_in_buffer_read_offset >= audio_algorithm_env->local_in_buffer_max) {
                audio_algorithm_env->local_in_buffer_read_offset = 0;
            }
        }
        else {
            memcpy(&audio_algorithm_env->aec_local_data[0], &audio_algorithm_env->local_in_buffer[begin], tail_len*sizeof(int16_t));
            head_len = AUDIO_ALG_AEC_SIZE - tail_len;
            memcpy(&audio_algorithm_env->aec_local_data[tail_len], &audio_algorithm_env->local_in_buffer[0], head_len*sizeof(int16_t));
            
            audio_algorithm_env->local_in_buffer_read_offset = head_len;
        }

#if ENABLE_NS
        if(execute && ((audio_alg_sel & AUDIO_ALG_NR_ENABLE)!=0)) {
            WebRtcNs_Process(audio_algorithm_env->ns_handle,
                                (short *)&audio_algorithm_env->aec_local_data[0],
                                0,
                                out_frame,
                                0);
            WebRtcNs_Process(audio_algorithm_env->ns_handle,
                                (short *)&audio_algorithm_env->aec_local_data[AUDIO_ALG_AEC_SIZE>>1],
                                0,
                                &out_frame[AUDIO_ALG_AEC_SIZE>>1],
                                0);
        }
        else {
            memcpy((void *)&out_frame[0], (void *)&audio_algorithm_env->aec_local_data[0], AUDIO_ALG_AEC_SIZE * sizeof(int16_t));
        }
#else
        memcpy((void *)&out_frame[0], (void *)&audio_algorithm_env->aec_local_data[0], AUDIO_ALG_AEC_SIZE * sizeof(int16_t));
#endif

#if ENABLE_AGC
        if(execute && ((audio_alg_sel & AUDIO_ALG_AGC_ENABLE)!=0)) {
            WebRtcAgc_Process(audio_algorithm_env->agc_handle,
                                out_frame, 0,
                                AUDIO_ALG_AEC_SIZE,
                                out_frame_middle, 0, 0,
                                &out_mic_level, 0,
                                &saturationWarning);
        }
        else {
            memcpy((void *)&out_frame_middle[0], (void *)&out_frame[0], AUDIO_ALG_AEC_SIZE * sizeof(int16_t));
        }
#else
        memcpy((void *)&out_frame_middle[0], (void *)&out_frame[0], AUDIO_ALG_AEC_SIZE * sizeof(int16_t));
#endif

#if ENABLE_AEC
        if(execute && ((audio_alg_sel & AUDIO_ALG_AEC_ENABLE)!=0)) {
            WebRtcAec_ProcessFrame(audio_algorithm_env->aec_core,
                                    &audio_algorithm_env->aec_remote_data[0],
                                    out_frame_middle, 0,
                                    &audio_algorithm_env->aec_out_buffer[audio_algorithm_env->aec_out_buffer_write_offset],
                                    0, 0);
        }
        else {
            memcpy((void *)&audio_algorithm_env->aec_out_buffer[audio_algorithm_env->aec_out_buffer_write_offset],
                                        (void *)&out_frame_middle[0], AUDIO_ALG_AEC_SIZE * sizeof(int16_t));
        }
#else
        memcpy((void *)&audio_algorithm_env->aec_out_buffer[audio_algorithm_env->aec_out_buffer_write_offset], 
                            (void *)&out_frame_middle[0], AUDIO_ALG_AEC_SIZE * sizeof(int16_t));
#endif

#if 0
       //if(pskeys.bt_options & PSKEY_ENABLE_AUDIO_PRINT_D) {
            for(uint32_t i=0; i<AUDIO_ALG_AEC_SIZE; i++) {
                int16_t data = audio_algorithm_env->aec_out_buffer[audio_algorithm_env->aec_out_buffer_write_offset+i];
                fputc(char2ascii[(data>>12)&0x0f], 0);
                fputc(char2ascii[(data>>8)&0x0f], 0);
                fputc(char2ascii[(data>>4)&0x0f], 0);
                fputc(char2ascii[(data)&0x0f], 0);
#if 0
                data = audio_algorithm_env->aec_remote_data[i];
                fputc(char2ascii[(data>>12)&0x0f], 0);
                fputc(char2ascii[(data>>8)&0x0f], 0);
                fputc(char2ascii[(data>>4)&0x0f], 0);
                fputc(char2ascii[(data)&0x0f], 0);
#endif
            }
            fputc('\n', 0);
        //}
#endif

        audio_algorithm_env->aec_out_buffer_write_offset += AUDIO_ALG_AEC_SIZE;
        if(audio_algorithm_env->aec_out_buffer_write_offset >= audio_algorithm_env->aec_out_buffer_max) {
            audio_algorithm_env->aec_out_buffer_write_offset = 0;
        }
    }

#if AUDIO_ALGO_DBG_WITH_IO
    gpio_clear(0);
#endif
    //uart_putc_noint('>');
    GLOBAL_INT_RESTORE();
}

__attribute__((section("iram_section"))) void audio_algorithm_recv_data(int16_t *mic, int16_t *esco_in, uint8_t esco_data_mute, int16_t *mcu_mic_buffer, int16_t *mcu_esco_in_buffer)
{
    int16_t *tmp, *tmp1, value;
    uint32_t i;
    
    tmp = audio_algorithm_get_local_in_write_buffer();
    tmp1 = audio_algorithm_get_plc_insert_buffer(esco_data_mute);

    if(esco_data_mute) {
        for(i=0; i<AUDIO_ALG_FRAME_SIZE; i++) {
            #if 1
            value = 0x0000;
            *tmp1++ = value;
#if AUDIO_ALGO_ESCO_IN_LOG
            if(audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_ESCO_IN) {
                uart_putc_noint(char2ascii[(value>>12)&0x0f]);
                uart_putc_noint(char2ascii[(value>>8)&0x0f]);
                uart_putc_noint(char2ascii[(value>>4)&0x0f]);
                uart_putc_noint(char2ascii[(value)&0x0f]);
            }
#endif
            // 新增：优先使用MCU mic数据
            if (mcu_mic_buffer != NULL) {
                value = mcu_mic_buffer[i];
            } else {
                value = *mic++;
            }
            *tmp++ = value;
#if AUDIO_ALGO_MIC_LOG
            if(audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_MIC) {
                uart_putc_noint(char2ascii[(value>>12)&0x0f]);
                uart_putc_noint(char2ascii[(value>>8)&0x0f]);
                uart_putc_noint(char2ascii[(value>>4)&0x0f]);
                uart_putc_noint(char2ascii[(value)&0x0f]);
            }
#endif
            #else
            *tmp1++ = 0x0000;
            *tmp++ = *mic++;
            #endif
        }
    }
    else {
        for(i=0; i<AUDIO_ALG_FRAME_SIZE; i++) {
            #if 1
            // 新增：优先使用MCU esco_in数据
            if (mcu_esco_in_buffer != NULL) {
                value = mcu_esco_in_buffer[i];
            } else {
                value = *esco_in++;
            }
            *tmp1++ = value;
#if AUDIO_ALGO_ESCO_IN_LOG
            if(audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_ESCO_IN) {
                uart_putc_noint(char2ascii[(value>>12)&0x0f]);
                uart_putc_noint(char2ascii[(value>>8)&0x0f]);
                uart_putc_noint(char2ascii[(value>>4)&0x0f]);
                uart_putc_noint(char2ascii[(value)&0x0f]);
            }
#endif
            // 新增：优先使用MCU mic数据
            if (mcu_mic_buffer != NULL) {
                value = mcu_mic_buffer[i];
            } else {
                value = *mic++;
            }
            *tmp++ = value;
#if AUDIO_ALGO_MIC_LOG
            if(audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_MIC) {
                uart_putc_noint(char2ascii[(value>>12)&0x0f]);
                uart_putc_noint(char2ascii[(value>>8)&0x0f]);
                uart_putc_noint(char2ascii[(value>>4)&0x0f]);
                uart_putc_noint(char2ascii[(value)&0x0f]);
            }
#endif
            #else
            *tmp1++ = *esco_in++;
            *tmp++ = *mic++;
            #endif
        }
    }
#if AUDIO_ALGO_MIC_LOG || AUDIO_ALGO_ESCO_IN_LOG
    if(audio_alg_print_sel & (AUDIO_ALGO_PRINT_SEL_ESCO_IN|AUDIO_ALGO_PRINT_SEL_MIC)) {
        uart_putc_noint('\r');
        uart_putc_noint('\n');
    }
#endif
}

__attribute__((section("iram_section"))) static void audio_algorithm_ipc_rx(void)
{
    struct task_msg_t *msg;
    
    ipc_dma_rx_int_clear();

    if(audio_algorithm_env == NULL) {
        printf("tx audio_algorithm_env null\r\n");
        return;
    }

    // if(audio_algorithm_env->ipc_dma_int_occur_status != 0) {
    //     audio_algorithm_env->ipc_dma_int_occur_status--;
    //     if(audio_algorithm_env->ipc_dma_int_occur_status > 0) {
    //         printf("ipc_dma_int_occur_status %d return\r\n",audio_algorithm_env->ipc_dma_int_occur_status);
    //         return;
    //     }
    // }

    int16_t *mic, *esco_in, *pdm_in, *tmp, value, i;

    if(ipc_get_esco_bb2dsp_tog(0)) {
        esco_in = (int16_t *)IPC_ESCO0_READ_BUFFER0;
    }
    else {
        esco_in = (int16_t *)IPC_ESCO0_READ_BUFFER1;
    }

	#if 1
	//mic from codec adc
    if(ipc_get_codec_adc_tog()) {
        mic = (int16_t *)IPC_CODEC_READ_BUFFER0;
    }
    else {
        mic = (int16_t *)IPC_CODEC_READ_BUFFER1;
    }
	#else
	/*mic from external i2s
    if(ipc_get_i2s_adc_tog()) {
        mic = (int16_t *)IPC_I2S_READ_BUFFER0;
    }
    else {
        mic = (int16_t *)IPC_I2S_READ_BUFFER1;
    }*/
    if(ipc_get_pdm_tog(0)) {
		mic = (int16_t *)IPC_PDM0_L_READ_BUFFER0;
	}
	else {
		mic = (int16_t *)IPC_PDM0_L_READ_BUFFER1;
	}
	#endif
	
	
#if 0
    if(last_mic_toggle) {
        last_mic_toggle = 0;
    }
    else {
        last_mic_toggle = 1;
    }
    memcpy((void *)&mic_data[last_mic_toggle][0], (void *)mic, AUDIO_ALG_FRAME_SIZE*2*sizeof(int16_t));
#endif
    //printf("mic=%x\r\n",mic[0]);
    

    #if 0
    // 新增：读取MCU ADPCM ringbuffer数据，准备用于mic和esco_in的赋值
    int16_t *mcu_mic_buffer = NULL;
    int16_t *mcu_esco_in_buffer = NULL;
    if (audio_algorithm_env->mcu_adpcm_ringbuf != NULL) {
        uint32_t used_size = y_ringbuf_get_used_size(audio_algorithm_env->mcu_adpcm_ringbuf);
        uint32_t need_bytes = AUDIO_ALG_FRAME_SIZE * 2 * sizeof(int16_t);  // 120字节（60个样本）
        
        if (used_size >= need_bytes) {

            g_cur_frame_from_mcu = true;
            // 分配缓冲区
            mcu_mic_buffer = pvPortMalloc(need_bytes);
            mcu_esco_in_buffer = pvPortMalloc(need_bytes);
            if (mcu_mic_buffer != NULL && mcu_esco_in_buffer != NULL) {
                // 从ringbuf读取PCM数据到缓冲区
                uint16_t read_size = y_ringbuf_read_clear(audio_algorithm_env->mcu_adpcm_ringbuf, 
                                                        (uint8_t *)mcu_mic_buffer, 
                                                        need_bytes);
                if (read_size == need_bytes) {
                    // 复制数据到esco_in缓冲区
                    memcpy(mcu_esco_in_buffer, mcu_mic_buffer, need_bytes);
                    //printf("Read MCU ADPCM data for mic/esco_in: %d bytes\r\n", read_size);
                } else {
                    printf("Failed to read MCU ADPCM data: %d/%d\r\n", read_size, need_bytes);
                    vPortFree(mcu_mic_buffer);
                    vPortFree(mcu_esco_in_buffer);
                    mcu_mic_buffer = NULL;
                    mcu_esco_in_buffer = NULL;
                }





                    // for(int i = 0;i<read_size;i++)
                    {
                        // if(i%16 == 0){
                        //     printf("\r\n");
                        // }
                            // printf("%02x ",mcu_mic_buffer[i]);

                            // printf("\r\n");
                    }


                  //  uart_put_data_noint((uint8_t *)mcu_mic_buffer,need_bytes);



            } else {
                if (mcu_mic_buffer) vPortFree(mcu_mic_buffer);
                if (mcu_esco_in_buffer) vPortFree(mcu_esco_in_buffer);
                mcu_mic_buffer = NULL;
                mcu_esco_in_buffer = NULL;
            }


         
        }
        
        else if(used_size != 0)    /* used_size < need_bytes   ——  ringbuf 剩余不足 120 字节 */
        {
            g_cur_frame_from_mcu = true;
            /* 1. 先统一申请 120 字节（60 sample）的缓冲区 */
            mcu_mic_buffer      = pvPortMalloc(need_bytes);
            mcu_esco_in_buffer  = pvPortMalloc(need_bytes);
    
            if (mcu_mic_buffer != NULL && mcu_esco_in_buffer != NULL) {
    
                /* 2. 统统清零，先保证静音 */
                memset(mcu_mic_buffer,     0, need_bytes);
                memset(mcu_esco_in_buffer, 0, need_bytes);
    
                if (used_size > 0) {
                    printf("size %d\r\n",used_size);
                    /* 3. 把 ringbuf 里现有的字节读出来，写到头部 */
                    uint16_t read_size = y_ringbuf_read_clear(
                                             audio_algorithm_env->mcu_adpcm_ringbuf,
                                             (uint8_t *)mcu_mic_buffer,
                                             used_size);          /* 只读 used_size */
    
                    /* 读出来多少都拷一份到 esco_in 区 */
                    memcpy(mcu_esco_in_buffer, mcu_mic_buffer, read_size);
    
                    /* 若需要可做 debug：
                       printf("Ringbuf <120B, read %u / %u bytes, rest filled 0\n",
                               read_size, need_bytes);
                    */
                }
                /* 4. 不足部分已经是 0 —— 补零完毕 */
    
            } else {
                printf("malloc fail\r\n");
                /* 5. 申请失败时的收尾，与上层保持一致 */
                if (mcu_mic_buffer)     vPortFree(mcu_mic_buffer);
                if (mcu_esco_in_buffer) vPortFree(mcu_esco_in_buffer);
                mcu_mic_buffer     = NULL;
                mcu_esco_in_buffer = NULL;
            }
        }
        
        //     else if(used_size == 0)
        // {
        //     g_cur_frame_from_mcu = false;
        // }

       
    }
    

      //printf("\r\n");
    
    audio_algorithm_recv_data(mic, esco_in, ipc_dma_esco_state_get(), mcu_mic_buffer, mcu_esco_in_buffer);
    audio_algorithm_recv_data(mic+AUDIO_ALG_FRAME_SIZE, esco_in+AUDIO_ALG_FRAME_SIZE, ipc_dma_esco_state_get(), 
                             mcu_mic_buffer ? mcu_mic_buffer+AUDIO_ALG_FRAME_SIZE : NULL, 
                             mcu_esco_in_buffer ? mcu_esco_in_buffer+AUDIO_ALG_FRAME_SIZE : NULL);




                              // 释放MCU缓冲区
    if (mcu_mic_buffer != NULL) {
        vPortFree(mcu_mic_buffer);
    }
    if (mcu_esco_in_buffer != NULL) {
        vPortFree(mcu_esco_in_buffer);
    }
   
     #else

    audio_algorithm_recv_data(mic, esco_in, ipc_dma_esco_state_get(),NULL,NULL);
    audio_algorithm_recv_data(mic+AUDIO_ALG_FRAME_SIZE, esco_in+AUDIO_ALG_FRAME_SIZE, ipc_dma_esco_state_get(),NULL,NULL);

    #endif 
   

#if 0
    msg = task_msg_alloc(AUDIO_IPC_DMA_RX, 0);
    task_msg_insert(msg);
#else
    // if(audio_algorithm_env->launch_algo_msg_count > 4) {
    //     audio_alg_launch(false);
    //     audio_alg_launch(false);
    // }
    // else {
    //     audio_algorithm_env->launch_algo_msg_count++;
    //     msg = task_msg_alloc(AUDIO_IPC_DMA_RX, 0);
    //     task_msg_insert(msg);
    // }
#endif
}

__attribute__((section("iram_section"))) static void audio_algorithm_ipc_tx(void)
{
    struct task_msg_t *msg;
    
    ipc_dma_tx_int_clear();
    
    if(audio_algorithm_env == NULL) {
        printf("tx audio_algorithm_env null\r\n");
        return;
    }

    // if(audio_algorithm_env->ipc_dma_int_occur_status != 0) {

    //     printf("tx ipc_dma_int_occur_status %d return\r\n",audio_algorithm_env->ipc_dma_int_occur_status);

    //     return;
    // }

#if AUDIO_ALGO_PTR_LOG
    if(audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_PTR) {
        uint16_t value;
        value = audio_algorithm_env->plc_buffer_aec_offset;
        uart_putc_noint('1');
        uart_putc_noint('A');
        uart_putc_noint(char2ascii[value/1000]);
        value %= 1000;
        uart_putc_noint(char2ascii[value/100]);
        value %= 100;
        uart_putc_noint(char2ascii[value/10]);
        value %= 10;
        uart_putc_noint(char2ascii[value]);
        uart_putc_noint('1');
        uart_putc_noint('B');
        value = audio_algorithm_env->plc_buffer_read_offset;
        uart_putc_noint(char2ascii[value/1000]);
        value %= 1000;
        uart_putc_noint(char2ascii[value/100]);
        value %= 100;
        uart_putc_noint(char2ascii[value/10]);
        value %= 10;
        uart_putc_noint(char2ascii[value]);
        uart_putc_noint('1');
        uart_putc_noint('C');
        value = audio_algorithm_env->plc_buffer_write_offset;
        uart_putc_noint(char2ascii[value/1000]);
        value %= 1000;
        uart_putc_noint(char2ascii[value/100]);
        value %= 100;
        uart_putc_noint(char2ascii[value/10]);
        value %= 10;
        uart_putc_noint(char2ascii[value]);
        uart_putc_noint('1');
        uart_putc_noint('D');
        value = audio_algorithm_env->plc_buffer_insert_offset;
        uart_putc_noint(char2ascii[value/1000]);
        value %= 1000;
        uart_putc_noint(char2ascii[value/100]);
        value %= 100;
        uart_putc_noint(char2ascii[value/10]);
        value %= 10;
        uart_putc_noint(char2ascii[value]);
        uart_putc_noint('2');
        uart_putc_noint('A');
        value = audio_algorithm_env->local_in_buffer_read_offset;
        uart_putc_noint(char2ascii[value/1000]);
        value %= 1000;
        uart_putc_noint(char2ascii[value/100]);
        value %= 100;
        uart_putc_noint(char2ascii[value/10]);
        value %= 10;
        uart_putc_noint(char2ascii[value]);
        uart_putc_noint('2');
        uart_putc_noint('B');
        value = audio_algorithm_env->local_in_buffer_write_offset;
        uart_putc_noint(char2ascii[value/1000]);
        value %= 1000;
        uart_putc_noint(char2ascii[value/100]);
        value %= 100;
        uart_putc_noint(char2ascii[value/10]);
        value %= 10;
        uart_putc_noint(char2ascii[value]);
        if((audio_alg_print_sel & (AUDIO_ALGO_PRINT_SEL_ESCO_OUT|AUDIO_ALGO_PRINT_SEL_SPK))==0) {
            uart_putc_noint('\r');
            uart_putc_noint('\n');
        }
    }
#endif

#if 0
    msg = task_msg_alloc(AUDIO_IPC_DMA_TX, 0);
    task_msg_insert(msg);
#else
    audio_algorithm_ipc_tx_handler(NULL);
#endif
}

void audio_algorithm_ipc_rx_handler(struct task_msg_t *msg)
{
    GLOBAL_INT_DISABLE();
    if(audio_algorithm_env->launch_algo_msg_count != 0) {
        audio_algorithm_env->launch_algo_msg_count--;
    }
    GLOBAL_INT_RESTORE();
    audio_alg_launch(true);
    audio_alg_launch(true);
}

__attribute__((section("iram_section")))  void audio_algorithm_ipc_tx_handler(struct task_msg_t *msg)
{
	uint8_t i;

    int16_t *spk, *esco_out, *spk_i2s;

    if(ipc_get_esco_dsp2bb_tog(0) == 0) {
        esco_out = (int16_t *)IPC_ESCO0_WRITE_BUFFER1;
    }
    else {
        esco_out = (int16_t *)IPC_ESCO0_WRITE_BUFFER0;
    }
    
    if(ipc_get_codec_dac_tog() == 0) {
        spk = (int16_t *)IPC_CODEC_WRITE_BUFFER1;
    }
    else {
        spk = (int16_t *)IPC_CODEC_WRITE_BUFFER0;
    }
    
 


    int16_t *spk_save = pvPortMalloc(120);

    #if 0

    // 新逻辑：mcu_esco_buffer参数为NULL，读取ringbuffer逻辑移到audio_algorithm_ipc_rx中
    audio_algorithm_send_data(spk, NULL, esco_out, spk_save, NULL);
    audio_algorithm_send_data(spk+AUDIO_ALG_FRAME_SIZE, NULL, esco_out+AUDIO_ALG_FRAME_SIZE, spk_save+AUDIO_ALG_FRAME_SIZE, NULL);
    #else


    int16_t *mcu_esco_in_buffer = NULL;

    uint32_t need_bytes = AUDIO_ALG_FRAME_SIZE * 2 * sizeof(int16_t);  // 120字节（60个样本）

    // 分配缓冲区
    mcu_esco_in_buffer = pvPortMalloc(need_bytes);

    memset(mcu_esco_in_buffer,0X00,need_bytes);

    if (audio_algorithm_env->mcu_adpcm_ringbuf != NULL) {
        uint32_t used_size = y_ringbuf_get_used_size(audio_algorithm_env->mcu_adpcm_ringbuf);
   

  extern uint8_t audio_algorithm_get_mcu_audio_timeout_flag(void);

 


        if ( (used_size > 1920)  ||  ((used_size > 0)&&(is_start == true)) ) {

            if (!g_cur_frame_from_mcu)
            {
                 g_cur_frame_from_mcu = true;
                 is_start = true;
            }

        
            
       
            
            if ( mcu_esco_in_buffer != NULL) {
                // 从ringbuf读取PCM数据到缓冲区
                uint16_t read_size = y_ringbuf_read_clear(audio_algorithm_env->mcu_adpcm_ringbuf, 
                                                        (uint8_t *)mcu_esco_in_buffer, 
                                                        need_bytes);
                if (read_size != need_bytes) {

                    //printf("1 read_size %d,need_bytes %d\r\n",read_size,need_bytes);
                    // 复制数据到esco_in缓冲区
                    // memset((uint8_t *)&mcu_esco_in_buffer[read_size], 0X00, need_bytes - read_size);
                        // 修正：使用字节指针进行正确的偏移
                    memset((uint8_t *)mcu_esco_in_buffer + read_size, 0x00, need_bytes - read_size);
                     
                    //printf("2 read_size %d,need_bytes %d\r\n",read_size,need_bytes);
                    //printf("Read MCU ADPCM data for mic/esco_in: %d bytes\r\n", read_size);
                }else{
                    //printf("3 read_size %d,need_bytes %d\r\n",read_size,need_bytes);
                }

            } 
        }


    }


    audio_algorithm_send_data(spk, NULL, esco_out, spk_save, (int16_t *)&mcu_esco_in_buffer[0]);
    audio_algorithm_send_data(spk+AUDIO_ALG_FRAME_SIZE, NULL, esco_out+AUDIO_ALG_FRAME_SIZE, spk_save+AUDIO_ALG_FRAME_SIZE, (int16_t *)&mcu_esco_in_buffer[AUDIO_ALG_FRAME_SIZE]);


    vPortFree(mcu_esco_in_buffer);
    mcu_esco_in_buffer = NULL;




    #endif


    #if 1


    uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->speaker_to_mcu_ringbuf);

    if( free_size > need_bytes){

        if (!g_cur_frame_from_mcu) {
            y_ringbuf_write(audio_algorithm_env->speaker_to_mcu_ringbuf, (uint8_t *)spk_save, 120);
        }else{
            memset((uint8_t *)spk_save,0x00,120);
            y_ringbuf_write(audio_algorithm_env->speaker_to_mcu_ringbuf, (uint8_t *)spk_save, 120);
        }

    }else{
        printf("total full\r\n");
    }


    extern uint8_t audio_algorithm_get_mcu_audio_timeout_flag(void);
    if (audio_algorithm_get_mcu_audio_timeout_flag != 0) {
        g_cur_frame_from_mcu = false;
        is_start = false;
    } 



         // 发送任务消息处理数据
         struct task_msg_t *task_msg = task_msg_alloc(AUDIO_ALGO_SEND_AUDIO_ENCODE_SPEAKER_DATA, 0);
         if(task_msg != NULL) {
             task_msg_insert(task_msg);
             //printf("Timer callback: Task message sent, used_size=%d\r\n", used_size);
         } else {
             printf("Timer callback: Failed to allocate task message\r\n");
         }

    #else
    if(audio_algorithm_env->speaker_data_enable) {
            //printf("g_cur_frame_from_mcu %d\r\n",g_cur_frame_from_mcu);
            // 新增：只对BT来源编码回传MCU
            if (!g_cur_frame_from_mcu) {
                // 本帧为MCU来源，不做ADPCM编码和写入ringbuf
                ///goto SKIP_ADPCM_ENCODE;


                uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->speaker_ringbuf);
                uint32_t adpcm_size = (AUDIO_ALG_FRAME_SIZE * 2) / 2;  // ADPCM编码后的大小（每个样本4位）
                if(free_size >= adpcm_size) {
                    uint8_t *adpcm_buffer = pvPortMalloc(adpcm_size);
                    if(adpcm_buffer != NULL) {
                        int encoded_bytes = ima_adpcm_encode(audio_algorithm_env->adpcm_encoder, 
                                                        adpcm_buffer, 
                                                        spk_save, 
                                                        AUDIO_ALG_FRAME_SIZE * 2);

                       
                        y_ringbuf_write(audio_algorithm_env->speaker_ringbuf, adpcm_buffer, encoded_bytes);
                        vPortFree(adpcm_buffer);
                        vPortFree(spk_save);
                    } else {
                        printf("Failed to allocate ADPCM buffer\r\n");
                    }
                } else {
                    printf("Ringbuf full, skipping write\r\n");
                }
            }
        
            else
            {


                uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->speaker_ringbuf);
                uint32_t adpcm_size = (AUDIO_ALG_FRAME_SIZE * 2) / 2;  // ADPCM编码后的大小（每个样本4位）
                if(free_size >= adpcm_size) {
                    uint8_t *adpcm_buffer = pvPortMalloc(adpcm_size);
                    if(adpcm_buffer != NULL) {
                        int encoded_bytes = ima_adpcm_encode(audio_algorithm_env->adpcm_encoder, 
                                                        adpcm_buffer, 
                                                        spk_save, 
                                                        AUDIO_ALG_FRAME_SIZE * 2);
                        memset(adpcm_buffer,0x00,encoded_bytes);
                        y_ringbuf_write(audio_algorithm_env->speaker_ringbuf, adpcm_buffer, encoded_bytes);
                        vPortFree(adpcm_buffer);
                        vPortFree(spk_save);
                    } else {
                        printf("Failed to allocate ADPCM buffer\r\n");
                    }
                } else {
                    printf("Ringbuf full, skipping write\r\n");
                }


                    // 新增：判断本帧是否为MCU来源
                    // if (audio_algorithm_env && audio_algorithm_env->mcu_adpcm_ringbuf) {
                        // uint32_t used_size = y_ringbuf_get_used_size(audio_algorithm_env->mcu_adpcm_ringbuf);
                        // uint32_t need_bytes = AUDIO_ALG_FRAME_SIZE * 2 * sizeof(int16_t);

                        extern uint8_t audio_algorithm_get_mcu_audio_timeout_flag(void);
                        if (audio_algorithm_get_mcu_audio_timeout_flag != 0) {
                            g_cur_frame_from_mcu = false;
                            is_start = false;
                        } 
                    // }
            }




    }

    #endif
SKIP_ADPCM_ENCODE:
        vPortFree(spk_save);


}
#if 0
static const struct task_msg_handler_t audio_algorithm_msg_table[] =
{
    {TASK_ID_IPC_DMA_RX,        audio_algorithm_ipc_rx_handler},
    {TASK_ID_IPC_DMA_TX,        audio_algorithm_ipc_tx_handler},
};
#endif


void audio_algorithm_ready(void)
{
    uint8_t channel;
        
    channel = ipc_alloc_channel(0);
    ipc_insert_msg(channel, IPC_MSG_DSP_READY, 0, NULL);
}

void audio_init(void *msg)
{
     uart_puts_noint("audio init\r\n");

    if(audio_algorithm_env != NULL) {
        return;
    }

    memset((void *)IPC_DSP_WRITE_BUFFER0, 0, 8*120);

    audio_algorithm_init();
    audio_algorithm_env->ipc_dma_int_occur_status = 40;

    ipc_dma_init(audio_algorithm_ipc_rx, audio_algorithm_ipc_tx);
    //REG_PL_WR(0x50000028,0x100); // enable ipc diagport
    _xtos_interrupt_enable(XCHAL_IPC_DMA_RX_INTERRUPT);
    _xtos_interrupt_enable(XCHAL_IPC_DMA_TX_INTERRUPT);
    //GLOBAL_INT_START();

    //audio_algorithm_ready();
	//app_register_default_task_handler(audio_task_handler);
   
#if AUDIO_ALGO_DBG_WITH_IO
    *(volatile uint32_t *)GPIO_DIR &= 0xfe;
#endif
}

#if AUDIO_ALGO_DBG_WITH_IO
#if 0
void uart_receive_char(uint8_t c)
{
    switch(c & 0xc0) {
        case 0x80:
            uart_putc_noint(audio_alg_sel);
            break;
        case 0x40:
            audio_alg_print_sel = c & (AUDIO_ALGO_PRINT_SEL_ESCO_OUT
                                        | AUDIO_ALGO_PRINT_SEL_ESCO_IN
                                        | AUDIO_ALGO_PRINT_SEL_SPK
                                        | AUDIO_ALGO_PRINT_SEL_MIC
                                        | AUDIO_ALGO_PRINT_SEL_PTR);
            break;
        case 0xc0:
            test_delay = 50*(c&0x3f);
            break;
        case 0x00:
            audio_alg_sel = c & (AUDIO_ALG_PLC_ENABLE|AUDIO_ALG_AEC_ENABLE|AUDIO_ALG_NR_ENABLE|AUDIO_ALG_AGC_ENABLE);
            break;
    }
}
#endif
#endif

// 新增：控制扬声器数据发送的函数实现
void audio_algorithm_enable_speaker_data(uint8_t enable)
{
    if(audio_algorithm_env != NULL) {
        audio_algorithm_env->speaker_data_enable = enable;
        if(!enable) {
            // 禁用时重置ringbuf
            if(audio_algorithm_env->speaker_ringbuf != NULL) {
                y_ringbuf_reset(audio_algorithm_env->speaker_ringbuf);
            }
        }
    }
}

uint8_t audio_algorithm_get_speaker_data_status(void)
{
    if(audio_algorithm_env != NULL) {
        return audio_algorithm_env->speaker_data_enable;
    }
    return 0;
}

// 新增：发送扬声器数据的任务处理函数
void audio_algorithm_send_speaker_data_task(struct task_msg_t *msg)
{
    if(audio_algorithm_env == NULL || !audio_algorithm_env->speaker_data_enable || audio_algorithm_env->speaker_ringbuf == NULL) {
        printf("Task handler: audio_algorithm_env is NULL or speaker_data disabled\r\n");
        return;
    }
    
#if 0
    // 检查是否有待处理的数据
    if(!audio_algorithm_env->pending_data_ready || audio_algorithm_env->pending_esco_data == NULL) {
        printf("Task handler: No pending data to process\r\n");
        return;
    }
    
    // 在任务上下文中进行ADPCM编码
    int16_t *current_esco_out = audio_algorithm_env->pending_esco_data;
    uint32_t adpcm_size = (AUDIO_ALG_FRAME_SIZE * 2) / 2;  // ADPCM编码后的大小（每个样本4位）
    
    // 检查ringbuf是否有足够空间
    uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->speaker_ringbuf);
    if(free_size >= adpcm_size) {
        // 分配ADPCM编码缓冲区
        uint8_t *adpcm_buffer = pvPortMalloc(adpcm_size);
        if(adpcm_buffer != NULL) {
            // 直接对esco_out的120字节数据进行ADPCM编码
            int encoded_bytes = ima_adpcm_encode(audio_algorithm_env->adpcm_encoder, 
                                               adpcm_buffer, 
                                               current_esco_out, 
                                               AUDIO_ALG_FRAME_SIZE * 2);  // 120字节 = 60个int16_t样本
            
            // 写入编码后的数据到ringbuf
            y_ringbuf_write(audio_algorithm_env->speaker_ringbuf, adpcm_buffer, encoded_bytes);
            
            //printf("Task: ADPCM encoded data written: %d bytes (original: %d bytes), compression ratio: %.2f\r\n", 
//                   encoded_bytes,
//                   AUDIO_ALG_FRAME_SIZE * 2 * sizeof(int16_t),
//                   (float)encoded_bytes / (AUDIO_ALG_FRAME_SIZE * 2 * sizeof(int16_t)));
            
            vPortFree(adpcm_buffer);
            
            // 清除待处理标志
            audio_algorithm_env->pending_data_ready = 0;
            audio_algorithm_env->pending_esco_data = NULL;
        } else {
            printf("Task: Failed to allocate ADPCM buffer\r\n");
        }
    } else {
        printf("Task: Ringbuf full, skipping write\r\n");
    }
#else
    // 在任务上下文中只处理ringbuf中已有的数据（发送到MCU）
    // ADPCM编码已经在中断上下文中完成
#endif
    
    // 处理ringbuf中已有的数据（发送到MCU）
    uint32_t used_size = y_ringbuf_get_used_size(audio_algorithm_env->speaker_ringbuf);
    if(used_size > 0) {
        // 尝试读取ADPCM编码的数据
        uint32_t data_size = (AUDIO_ALG_FRAME_SIZE * 2) / 2;  // ADPCM编码后的大小
        if(used_size < data_size) {
            data_size = used_size;  // 读取所有可用数据
        } else {
            // 可用数据足够，取一个30的整倍数
            uint32_t count30 = used_size / 30;
            uint32_t max30 = count30 * 30;
            if (max30 > 60) {
                max30 = 60;
            }
            data_size = max30;
        }
        
        if(data_size > 0) {
            uint8_t *send_buffer = pvPortMalloc(data_size);
            if(send_buffer != NULL) {
                // 从ringbuf读取ADPCM编码数据
                uint16_t read_size = y_ringbuf_read_clear(audio_algorithm_env->speaker_ringbuf, send_buffer, data_size);
                
                if(read_size > 0) {
                    //printf("Task: Sending ADPCM data to MCU, size=%d\r\n", read_size);
                    
                    // 使用ipc_msg_with_payload_send发送ADPCM编码数据
                    ipc_msg_with_payload_send(IPC_MSG_SPEAKER_AUDIO_DATA,
                                            NULL, 0,  // 没有header
                                            send_buffer,
                                            read_size,
                                            NULL);  // 没有callback
                }
                
                vPortFree(send_buffer);
            }
        }
    }
}

// 新增：定时器回调函数实现
void audio_algorithm_send_data_callback(void)
{
    if(audio_algorithm_env == NULL || !audio_algorithm_env->speaker_data_enable || audio_algorithm_env->speaker_ringbuf == NULL) {
        return;
    }
    
#if 0
    // 检查是否有待处理的数据
    if(audio_algorithm_env->pending_data_ready && audio_algorithm_env->pending_esco_data != NULL) {
        // 发送任务消息处理数据
        struct task_msg_t *task_msg = task_msg_alloc(AUDIO_ALGO_SEND_SPEAKER_DATA, 0);
        if(task_msg != NULL) {
            task_msg_insert(task_msg);
            //printf("Timer callback: Task message sent for pending data\r\n");
        } else {
            printf("Timer callback: Failed to allocate task message\r\n");
        }
    }
#else


#if 1

if(audio_algorithm_env->speaker_data_enable) {


        uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->speaker_ringbuf);
        uint32_t adpcm_size = (AUDIO_ALG_FRAME_SIZE * 2) / 2;  // ADPCM编码后的大小（每个样本4位）
        if(free_size >= adpcm_size) {
            uint8_t *adpcm_buffer = pvPortMalloc(adpcm_size);
            uint8_t *spk_save = pvPortMalloc(120);


            uint16_t used_len = y_ringbuf_get_used_size(audio_algorithm_env->speaker_to_mcu_ringbuf);

            if(used_len >= 120){

                uint16_t read_len = y_ringbuf_read_clear(audio_algorithm_env->speaker_to_mcu_ringbuf,spk_save,120);
            }else{
                printf("used_len %d\r\n",used_len);
            }

            if(adpcm_buffer != NULL) {
                int encoded_bytes = ima_adpcm_encode(audio_algorithm_env->adpcm_encoder, 
                                                adpcm_buffer, 
                                                (int16_t *)spk_save, 
                                                AUDIO_ALG_FRAME_SIZE * 2);

               
                y_ringbuf_write(audio_algorithm_env->speaker_ringbuf, adpcm_buffer, encoded_bytes);
                vPortFree(adpcm_buffer);
                vPortFree(spk_save);
            } else {
                printf("Failed to allocate ADPCM buffer\r\n");
            }
        } else {
            printf("Ringbuf full, skipping write\r\n");
        }
    

   

}


#endif



























    // 检查ringbuf中是否有数据（ADPCM编码后的大小）
    uint32_t used_size = y_ringbuf_get_used_size(audio_algorithm_env->speaker_ringbuf);
    uint32_t min_data_size = (AUDIO_ALG_FRAME_SIZE * 2) / 2;  // ADPCM编码后两帧数据的大小
    
    if(used_size >= min_data_size) {
        // 发送任务消息处理数据
        struct task_msg_t *task_msg = task_msg_alloc(AUDIO_ALGO_SEND_SPEAKER_DATA, 0);
        if(task_msg != NULL) {
            task_msg_insert(task_msg);
            //printf("Timer callback: Task message sent, used_size=%d\r\n", used_size);
        } else {
            printf("Timer callback: Failed to allocate task message\r\n");
        }
    }
#endif
}

__attribute__((section("iram_section")))
void audio_algorithm_send_data(int16_t *spk,
                               int16_t *spk_i2s,
                               int16_t *esco_out,
                               int16_t *spk_dup,
                               int16_t *mcu_esco_buffer)
{
    int16_t *tmp, value;
    uint32_t i, j;

    /* ---------- ① 从 PLC 输出读取 30 sample 写本地扬声器 ---------- */
    tmp = audio_algorithm_get_plc_out_buffer();

    for (i = 0; i < AUDIO_ALG_FRAME_SIZE; i++) {
        value = *tmp++;

        if (spk)      { *spk++      = value; }
        if (spk_i2s)  { *spk_i2s++  = value; }
        if (spk_dup)  { *spk_dup++  = value; }   /* <<< 同步复制 */

#if AUDIO_ALGO_SPK_LOG
        if (audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_SPK) {
            uart_putc_noint(char2ascii[(value >> 12) & 0x0f]);
            uart_putc_noint(char2ascii[(value >>  8) & 0x0f]);
            uart_putc_noint(char2ascii[(value >>  4) & 0x0f]);
            uart_putc_noint(char2ascii[(value      ) & 0x0f]);
        }
#endif
    }

    /* ---------- ② 把 AEC 结果送 eSCO，不再复制到 spk_dup ---------- */
    // 新增：优先使用MCU缓冲区数据
    if (mcu_esco_buffer != NULL) {
        // 使用MCU缓冲区数据发送到esco_out
        for (i = 0; i < AUDIO_ALG_FRAME_SIZE; i++) {
            value = mcu_esco_buffer[i];
            if (esco_out) { *esco_out++ = value; }
        }

        //printf("1\r\n");
    } else {
        //printf("2\r\n");
        // 原有的AEC处理逻辑
        i   = audio_algorithm_env->aec_out_buffer_max
            - audio_algorithm_env->aec_out_buffer_read_offset;

        tmp = &audio_algorithm_env->aec_out_buffer[
                audio_algorithm_env->aec_out_buffer_read_offset];

        if (i >= AUDIO_ALG_FRAME_SIZE) {
            i = AUDIO_ALG_FRAME_SIZE;
            audio_algorithm_env->aec_out_buffer_read_offset += AUDIO_ALG_FRAME_SIZE;
            if (audio_algorithm_env->aec_out_buffer_read_offset
                  >= audio_algorithm_env->aec_out_buffer_max) {
                audio_algorithm_env->aec_out_buffer_read_offset = 0;
            }
            j = 0;
        } else {
            j = AUDIO_ALG_FRAME_SIZE - i;
            audio_algorithm_env->aec_out_buffer_read_offset = j;
        }

        /* ②-1 先发尾巴 */
        for (; i > 0; i--) {
            value = *tmp++;
            if (esco_out) { *esco_out++ = value; }

    #if AUDIO_ALGO_ESCO_OUT_LOG
            if (audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_ESCO_OUT) {
                uart_putc_noint(char2ascii[(value >> 12) & 0x0f]);
                uart_putc_noint(char2ascii[(value >>  8) & 0x0f]);
                uart_putc_noint(char2ascii[(value >>  4) & 0x0f]);
                uart_putc_noint(char2ascii[(value      ) & 0x0f]);
            }
    #endif
        }

        /* ②-2 再补头部 wrap-around */
        tmp = &audio_algorithm_env->aec_out_buffer[0];
        for (; j > 0; j--) {
            value = *tmp++;
            if (esco_out) { *esco_out++ = value; }

    #if AUDIO_ALGO_ESCO_OUT_LOG
            if (audio_alg_print_sel & AUDIO_ALGO_PRINT_SEL_ESCO_OUT) {
                uart_putc_noint(char2ascii[(value >> 12) & 0x0f]);
                uart_putc_noint(char2ascii[(value >>  8) & 0x0f]);
                uart_putc_noint(char2ascii[(value >>  4) & 0x0f]);
                uart_putc_noint(char2ascii[(value      ) & 0x0f]);
            }
    #endif
        }
    }
}

// 新增：处理MCU发送的ADPCM音频数据
__attribute__((section("iram_section")))  void audio_algorithm_recv_mcu_adpcm_data(uint8_t *adpcm_data, uint32_t length)
{
    if(audio_algorithm_env == NULL || audio_algorithm_env->mcu_adpcm_ringbuf == NULL || 
       audio_algorithm_env->adpcm_decoder == NULL) {
        printf("MCU ADPCM components not initialized\r\n");
        return;
    }

    // 检查ringbuf是否有足够空间
    // uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->mcu_adpcm_ringbuf);
    // uint32_t need_bytes = length * 2 * sizeof(int16_t);  // ADPCM解码后数据量：120字节ADPCM -> 240个PCM样本 -> 480字节
    
    // if(free_size < need_bytes) {
    //     printf("MCU ADPCM ringbuf full, free=%d, need=%d, skipping data\r\n", free_size, need_bytes);
    //     return;
    // }

    // 解码ADPCM数据为PCM
    int decoded_samples = ima_adpcm_decode(audio_algorithm_env->adpcm_decoder,
                                         audio_algorithm_env->mcu_pcm_buffer,
                                         adpcm_data,
                                         length);

    if(decoded_samples > 0) {
        // 将解码后的PCM数据写入ringbuf
        uint32_t pcm_bytes = decoded_samples * sizeof(int16_t);




    //     printf("use length=%d,free %d\r\n",
    //          y_ringbuf_get_used_size(audio_algorithm_env->mcu_adpcm_ringbuf),
    //          y_ringbuf_get_free_size(audio_algorithm_env->mcu_adpcm_ringbuf)
    // );

                
        // 检查ringbuf是否有足够空间
        uint32_t free_size = y_ringbuf_get_free_size(audio_algorithm_env->mcu_adpcm_ringbuf);
        
        if(free_size < pcm_bytes) {
            printf("MCU ADPCM ringbuf full, free=%d, need=%d, skipping data\r\n", free_size, pcm_bytes);
            return;
        }

        
        y_ringbuf_write(audio_algorithm_env->mcu_adpcm_ringbuf, 
                       (uint8_t *)audio_algorithm_env->mcu_pcm_buffer, 
                       pcm_bytes);


        //uart_put_data_noint((uint8_t *)audio_algorithm_env->mcu_pcm_buffer,pcm_bytes);
        //printf("MCU ADPCM decoded: %d bytes -> %d samples (%d bytes)\r\n", length, decoded_samples, pcm_bytes);
        
        // 调试：打印前几个解码后的样本值
        // printf("First 10 decoded samples: ");
        // for(int i = 0; i < 10 && i < decoded_samples; i++) {
        //     printf("%d ", audio_algorithm_env->mcu_pcm_buffer[i]);
        // }
        // printf("\r\n");
        
    } else {
        printf("MCU ADPCM decode failed, length=%d\r\n", length);
    }
}
